﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace nMongo
{
    public class MongoReferenceMapping
    {
        public Type ReferenceType { get; set; }
        public string ReferenceMember { get; set; }
        public string ReferenceCollectionName { get; set; }
        public Type ReferencedByType { get; set; }
        public string ReferencedByMember { get; set; }
        public string ReferencedByCollectionName { get; set; }
    }

    public class MongoAssociation
    {
        public MongoReferenceMapping ReferenceMapping { get; set; }

        public void OneToMany<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TSource, object>> destinationMember)
        {
            MongoReferenceMapping mapping = new MongoReferenceMapping();
            mapping.ReferencedByType = sourceMember.Parameters[0].Type;
            mapping.ReferencedByMember = (sourceMember.Body as MemberExpression ?? ((UnaryExpression)sourceMember.Body).Operand as MemberExpression).Member.Name;
            mapping.ReferencedByCollectionName = Helpers.MongoCollectionHelper.GetCollectionNameFromType(mapping.ReferencedByType);

            mapping.ReferenceType = destinationMember.Parameters[0].Type;
            mapping.ReferenceMember = (destinationMember.Body as MemberExpression ?? ((UnaryExpression)destinationMember.Body).Operand as MemberExpression).Member.Name;
            mapping.ReferenceCollectionName = Helpers.MongoCollectionHelper.GetCollectionNameFromType(mapping.ReferenceType);
        }
    }

    public static class MongoMapset
    {
        static MongoMapset()
        {
            ReferencesList = new List<MongoReferenceMapping>();
        }

        public static List<MongoReferenceMapping> ReferencesList { get; set; }


        public static void AddReference<TReferencedBy, TReference>(string referencedByMemberName, string referenceMemberName)
        {
            lock (typeof(MongoMapset))
            {
                MongoMapset.ReferencesList.Add(new MongoReferenceMapping
                {
                    ReferenceCollectionName = Helpers.MongoCollectionHelper.GetCollectionNameFromType<TReference>(),
                    ReferencedByCollectionName = Helpers.MongoCollectionHelper.GetCollectionNameFromType<TReferencedBy>(),
                    ReferencedByMember = referencedByMemberName,
                    ReferencedByType = typeof(TReferencedBy),
                    ReferenceMember = referencedByMemberName,
                    ReferenceType = typeof(TReference)
                });

            }
        }

        public static MongoAssociation MapAssociation()
        {
            return new MongoAssociation();
        }
    }
}
